#ifndef _DINOSAURIA_H
#define _DINOSAURIA_H

#include <iostream>
#include <string>
#include <typeinfo>

class Dinosauria {
public:
	/* **************************************************************\
        |*              constructeurs / destructeur                     *|
	 \****************************************************************/
	Dinosauria() :
			nom("Dinosaure"), longueur(0), hauteur(0) {
		this->poids = Dinosauria::newDouble(0);
	}

	Dinosauria(std::string n, double p, double l, double h) :
			nom(n), longueur(l), hauteur(h) {
		this->poids = Dinosauria::newDouble(p);
	}

	virtual ~Dinosauria() {
		Dinosauria::deleteDouble(&(this->poids));
	}

	Dinosauria(const Dinosauria &copy) :  Dinosauria(copy.nom, *copy.poids, copy.longueur, copy.hauteur){
	}

	Dinosauria& operator=(const Dinosauria &copy) {
		if (this != &copy) {
			internalCopy(copy);
			Dinosauria::deleteDouble(&(this->poids));
			this->poids = Dinosauria::newDouble(*copy.poids);
		}

		return *this;
	}

	/* **************************************************************\
        |*              m�thodes publiques                              *|
	 \****************************************************************/
	virtual std::string manger() const = 0;
	virtual std::string localiser() const = 0;
	virtual Dinosauria* cloneOf() const = 0;

	inline virtual std::string classifier() const {
		return Dinosauria::strChopTypeinfo(typeid(this).name());
	}

	/* ***************************\
        |*     setteur / getteur     *|
	 \*****************************/
	inline std::string getNom() const {
		return this->nom;
	}

	inline double getPoids() const {
		return *(this->poids);
	}

	inline double getLongueur() const {
		return this->longueur;
	}

	inline double getHauteur() const {
		return this->hauteur;
	}

	inline void setPoids(double p) {
		*this->poids = p;
	}

	inline void setLongueur(double l) {
		this->longueur = l;
	}

	inline void setHauteur(double h) {
		this->hauteur = h;
	}

	/* ***************************\
        |*     m�thodes amies        *|
	 \*****************************/
	inline friend std::ostream &operator<<(std::ostream &out,
			const Dinosauria&copy) {
		copy.print(out);
		return out;
	}

protected:
	/* **************************************************************\
        |*              m�thodes priv�es                                *|
	 \****************************************************************/
	inline void internalCopy(const Dinosauria &src) {
		this->nom = src.nom;
		this->longueur = src.longueur;
		this->hauteur = src.hauteur;
	}

	inline virtual void print(std::ostream&out) const {
		out << "nom\t\t\t: " << nom << std::endl << "poids\t\t\t: " << *poids
				<< " kg" << std::endl << "longueur\t\t: " << longueur << " m"
				<< std::endl << "hauteur\t\t\t: " << hauteur << " m"
				<< std::endl;
	}

	/* **************************************************************\
        |*              m�thodes priv�es statiques                      *|
	 \****************************************************************/
	inline static double* newDouble(double d) {
		double* newPoids = nullptr;
		try {
			newPoids = new double;

			if (newPoids == nullptr)
				throw "probleme allocation memoire : newDouble()";

			*newPoids = d;

			return newPoids;
		} catch (char* str) {
			std::cerr << str;
		}
		return nullptr;
	}

	inline static void deleteDouble(double** d) {
		if (*d)
			delete *d;

		*d = nullptr;
	}

	inline static std::string strChopTypeinfo(std::string str) {
		str.erase(0, 2);

		int i = 0;
		while (isdigit(str[i])) {
			str.erase(0, 1);
		}

		return str;
	}

	/* **************************************************************\
        |*              attributs                                       *|
	 \****************************************************************/
	std::string nom;
	double *poids;
	double longueur;
	double hauteur;
};

#endif
